home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-04-05 | 4.0 KB | 153 lines | [TEXT/CWIE] |
- unit MyInterruptSafeMemory;
-
- interface
-
- uses
- Types;
-
- { memory is allocated in chunk_size units }
- { chunk_size must be a multiple of 16 }
-
- function MemoryPoolCreate( var pool: univ Ptr; size: longint; chunk_size: longint ): OSErr;
- procedure MemoryPoolDestroy( var pool: univ Ptr );
-
- function MemoryPoolAllocate( pool: univ Ptr; var data: Ptr; size: longint ): OSErr;
- procedure MemoryPoolFree( pool: univ Ptr; var data: Ptr );
-
- implementation
-
- uses
- OSUtils, Errors, OpenTransport,
- MyMemory, MyAssertions, MyLowLevel;
-
- {$align powerpc}
- type
- CountsArray = array[0..0] of longint;
- CountsArrayPtr = ^CountsArray;
- PoolRecord = record
- chunk_size: longint;
- chunk_count: longint;
- last_checked: longint;
- counts: CountsArrayPtr;
- bits: Ptr;
- data: Ptr;
- end;
- PoolPtr = ^PoolRecord;
- {$align reset}
-
- function AtmicClearBit( pp: PoolPtr; bit: longint ): boolean;
- begin
- AtmicClearBit := OTAtomicClearBit( UInt8(AddPtrLong( pp^.bits, bit div 8 )^), bit mod 8 );
- end;
-
- function AtmicSetBit( pp: PoolPtr; bit: longint ): boolean;
- begin
- AtmicSetBit := OTAtomicSetBit( UInt8(AddPtrLong( pp^.bits, bit div 8 )^), bit mod 8 );
- end;
-
- function MemoryPoolCreate( var pool: univ Ptr; size: longint; chunk_size: longint ): OSErr;
- var
- err: OSErr;
- i, chunk_count, bits_size: longint;
- pp: PoolPtr;
- junk_bool: boolean;
- begin
- Assert( (chunk_size > 0) & (size > 0) );
- Assert( chunk_size mod 16 = 0 );
-
- chunk_count := (size + chunk_size - 1) div chunk_size;
- size := chunk_count * chunk_size;
- bits_size := (chunk_count + 31) div 32 * 4;
- err := MNewPtr( pool, SizeOf(PoolRecord) + chunk_count * SizeOf(longint) + bits_size + size );
- if err = noErr then begin
- pp := PoolPtr(pool);
- pp^.chunk_size := chunk_size;
- pp^.chunk_count := chunk_count;
- pp^.last_checked := 0;
- pp^.counts := CountsArrayPtr( AddPtrLong( pool, SizeOf(PoolRecord) ) );
- pp^.bits := AddPtrLong( pp^.counts, chunk_count * SizeOf(longint) );
- pp^.data := AddPtrLong( pp^.bits, bits_size );
- for i := 0 to chunk_count - 1 do begin
- junk_bool := AtmicClearBit( pp, i );
- pp^.counts^[i] := 0;
- end;
- end;
- MemoryPoolCreate := err;
- end;
-
- procedure MemoryPoolDestroy( var pool: univ Ptr );
- begin
- MDisposePtr( pool );
- end;
-
- function MemoryPoolAllocate( pool: univ Ptr; var data: Ptr; size: longint ): OSErr;
- var
- err: OSErr;
- i, j, chunks_needed, last_checked, found: longint;
- pp: PoolPtr;
- junk_bool: boolean;
- begin
- Assert( pool <> nil );
- pp := PoolPtr(pool);
- chunks_needed := (size + pp^.chunk_size - 1) div pp^.chunk_size;
- last_checked := pp^.last_checked;
- i := last_checked;
- found := -1;
- repeat
- if i + chunks_needed <= pp^.chunk_count then begin
- found := i;
- j := i;
- while j < i + chunks_needed do begin
- if AtmicSetBit( pp, j ) then begin
- while j > i do begin
- junk_bool := AtmicClearBit( pp, j );
- Dec(j);
- end;
- found := -1;
- leave;
- end;
- Inc(j);
- end;
- if found >= 0 then begin
- leave;
- end;
- end;
- Inc(i);
- if i = pp^.chunk_count then begin
- i := 0;
- end;
- until i = last_checked;
- if found >= 0 then begin
- pp^.counts^[found] := chunks_needed;
- data := AddPtrLong( pp^.data, found * pp^.chunk_size );
- pp^.last_checked := (found + chunks_needed) mod pp^.chunk_count;
- err := noErr;
- end else begin
- data := nil;
- err := memFullErr;
- end;
- MemoryPoolAllocate := err;
- end;
-
- procedure MemoryPoolFree( pool: univ Ptr; var data: Ptr );
- var
- found, count, i: longint;
- pp: PoolPtr;
- junk_bool: boolean;
- begin
- Assert( pool <> nil );
- pp := PoolPtr(pool);
- Assert( SubPtrPtr( data, pp^.data ) mod pp^.chunk_size = 0 );
- found := SubPtrPtr( data, pp^.data ) div pp^.chunk_size;
- Assert( (0 <= found) & (found < pp^.chunk_count) );
- count := pp^.counts^[found];
- Assert( (0 < count) & (found + count <= pp^.chunk_count) );
- for i := found to found + count - 1 do begin
- junk_bool := AtmicClearBit( pp, i );
- Assert( junk_bool );
- end;
- data := nil;
- end;
-
- end.
-